﻿#region Copyright and License Notice
// Copyright (C)2010-2016 - Rob Levine and other contributors
// http://configgen.codeplex.com
// 
// This file is part of ConfigGen.
// 
// ConfigGen is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// 
// ConfigGen is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
// 
// You should have received a copy of the GNU General Public License and 
// the GNU Lesser General Public License along with ConfigGen.  
// If not, see <http://www.gnu.org/licenses/>
#endregion

using System;
using System.IO;

namespace ConfigGen.Core.TemplateLoader
{
    /// <summary>
    /// Loads a template from a file
    /// </summary>
    public class FileTemplateLoader : ITemplateLoader
    {
        private readonly ITemplatePreferencesLoader _templatePreferencesLoader;
        private TemplatePreferences _templatePreferences;
        private byte[] _template;

        /// <summary>
        /// Initializes a new instance of the <see cref="FileTemplateLoader"/> class.
        /// </summary>
        /// <param name="templatePreferencesLoader">The template preferences extractor.</param>
        /// <exception cref="ArgumentNullException">Thrown if <paramref name="templatePreferencesLoader"/> is null.</exception>
        public FileTemplateLoader(ITemplatePreferencesLoader templatePreferencesLoader)
        {
            if (templatePreferencesLoader == null)
            {
                throw new ArgumentNullException("templatePreferencesLoader");
            }

            _templatePreferencesLoader = templatePreferencesLoader;
        }

        #region ITemplateLoader Members

        /// <summary>
        /// Loads the template from a file.
        /// </summary>
        /// <param name="args">The filename of the template file as the only item in the array</param>
        /// <exception cref="ArgumentNullException">Thrown if <paramref name="args"/> is null, or if it contains a null entry</exception>
        /// <exception cref="ArgumentException">Thrown if the args array does not have exactly one entry, or if the one entry is an empty string</exception>
        /// <exception cref="FileNotFoundException">Thrown if the specified template file is not found</exception>
        public void LoadTemplate(string[] args)
        {
            if (args == null) throw new ArgumentNullException("args");
            if (args.Length != 1) throw new ArgumentException("LoadTemplate expectes a single argument, the filename, but got " + args.Length, "args");

            if (args[0] == null) throw new ArgumentNullException("args", "Entry in args array must not be null");
            if (args[0].Length == 0) throw new ArgumentException("Entry in args array must not be an empty string", "args");

            var file = new FileInfo(args[0]);
            if (!file.Exists) throw new FileNotFoundException("Template file not found: " + file.FullName);

            using (var fileStream = new FileStream(file.FullName, FileMode.Open, FileAccess.Read, FileShare.Read))
            using (var loadedTemplateStream = new MemoryStream())
            {
                _templatePreferences = _templatePreferencesLoader.LoadPreferences(fileStream, loadedTemplateStream);
                loadedTemplateStream.Position = 0;
                int length = (int)loadedTemplateStream.Length;
                _template = new byte[length];
                loadedTemplateStream.Read(_template, 0, length);
            }
        }

        /// <summary>
        /// Returns a stream containing the raw temaple bytes.
        /// </summary>
        /// <returns>
        /// A stream containing the raw temaple bytes.
        /// </returns>
        public Stream GetTemplateStream()
        {
            return new MemoryStream(_template);
        }

        /// <summary>
        /// Gets the template preferences loaded by the instance, if any, otherwise null.
        /// </summary>
        public TemplatePreferences TemplatePreferences
        {
            get { return _templatePreferences; }
        }

        #endregion
    }
}
